/*
 * awire.c
 *
 *  Created on: Aug 2, 2013
 *      Author: Ken Arok
 *
 *      Revision history:
 *      ---------------------------------------------------------
 *      Date			|	Revised by		|	Description
 *      ---------------------------------------------------------
 *      1. Aug 2, 2013	|	Yosef			| New establishment
 *
 *
 * \file
 *
 * \brief Hardware Abstraction Layer of aWire UART Controller UC3C0512C
 *
 * Copyright (c) 2013 PT Hanindo Automation Solutions. All rights reserved.
 *
 */

#include "config_board.h"

#if BOARD_1_0_USED

#include "compiler.h"
#include "awire.h"


/** \brief Enable internal 120MHz RC oscillator for aWire UART.
 *
 * \param _awire	Base address of the aWire instance.
 *
 * \return Status
 *	\retval	AWIRE_ERR_INVALID_ARG	Failed
 *	\retval	AWIRE_STATUS_OK			Success
 *
 */
static awire_status_code_t awire_enable_clock(volatile avr32_aw_t *_awire)
{
	if(_awire == NULL) return AWIRE_ERR_INVALID_ARG;

	//! Enable aWire Clock
	_awire->clkr = AWIRE_CRR_CLKEN_MASK;

	//! Check Status Register
	while(!(_awire->sr & AWIRE_SR_CENABLED_MASK));

	return AWIRE_STATUS_OK;

}

/** \brief Select mode operation for aWire UART.
 *
 * \param _awire	Base address of the aWire instance.
 * \param _mode		Mode operation (DISABLE, RECEIVE, TRANSMIT or SYNC).
 *
 * \return Status
 *	\retval	AWIRE_ERR_INVALID_ARG	Failed
 *	\retval	AWIRE_STATUS_OK			Success
 *
 */
static awire_status_code_t awire_select_mode(volatile avr32_aw_t *_awire, unsigned long _mode)
{
	if(_awire == NULL) return AWIRE_ERR_INVALID_ARG;

	// Select aWire user interface mode
	_awire->ctrl = _mode;

	return AWIRE_STATUS_OK;
}


/** \brief Set baudrate for aWire UART.
 *
 * \param _awire		Base address of the aWire instance.
 * \param _baudrate		Set point of baudrate.
 *
 * \return Status
 *	\retval	AWIRE_ERR_INVALID_ARG	Failed
 *	\retval	AWIRE_STATUS_OK			Success
 *
 */
static awire_status_code_t awire_set_baudrate(volatile avr32_aw_t *_awire, unsigned long _baudrate)
{
	unsigned long _brate;

	if(_awire == NULL) return AWIRE_ERR_INVALID_ARG;

	// Wait busy flag is cleared
	while((_awire->sr & AWIRE_SR_BUSY_MASK));

	// Set baudrate
	_brate = 8*120000000UL/_baudrate;
	_awire->brr = _brate;

	// Wait busy flag is cleared
	while((_awire->sr & AWIRE_SR_BUSY_MASK));

	return AWIRE_STATUS_OK;
}


awire_status_code_t awire_init(volatile avr32_aw_t *_awire, const awire_options_t *_opt)
{
	// Enable clock 120RCM
	if(awire_enable_clock(_awire) == AWIRE_ERR_INVALID_ARG) return AWIRE_ERR_INVALID_ARG;

	// Initialize mode
	if(awire_select_mode(_awire, _opt->mode) == AWIRE_ERR_INVALID_ARG) return AWIRE_ERR_INVALID_ARG;

	// Set Baudrate
	if(awire_set_baudrate(_awire, _opt->baudrate) == AWIRE_ERR_INVALID_ARG) return AWIRE_ERR_INVALID_ARG;

	return AWIRE_STATUS_OK;
}


awire_status_code_t awire_set_mode(volatile avr32_aw_t *_awire, const awire_options_t *_opt)
{
	if(awire_select_mode(_awire, _opt->mode) == AWIRE_ERR_INVALID_ARG) return AWIRE_ERR_INVALID_ARG;
	else return AWIRE_STATUS_OK;
}

#endif /* BOARD_1_0_USED */
